# -*- coding: utf-8 -*-
"""
Created on Tue Jul  9 09:11:12 2019

@author: MS

"""

import numpy as np
from subfuns import AnalysisData,OneHot,initialpara,BP,BP_Linear
import matplotlib.pyplot as plt
from sklearn import datasets

#--------作图时显示中文字符-------------
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False

#%%====================================
#             导入数据集
#====================================
#----------------1.iris鸢尾花数据集----------------
# 特征数4，均为连续型数据
# 类别数3,代表鸢尾花类型
# 样本数: 50+50+50
iris=datasets.load_iris()
X1=iris["data"]
Y1=iris["target"]  #Y=0,1,2
#---------将Y=0,1,2分别转换为 [1,0,0],[0,1,0],[0,0,1]----------
Y1=OneHot(Y1.reshape(-1,1)+1,[[type(' '),1,2,3]],[False])
#----------------2.wine酒类数据集-------------------
# 特征数13,均为连续型数据
# 类别数3，代表酒的类别
# 样本数:59+71+48
wine=datasets.load_wine()
X2=wine["data"]
Y2=wine["target"]  #Y=0,1,2
Y2=OneHot(Y2.reshape(-1,1)+1,[[type(' '),1,2,3]],[False])
#%%=================================================
#       在鸢尾花数据集上进行计算
#                数据集设置以及网络参数设置
#===================================================
X=X1  #若X=X1,Y=Y1表示采用鸢尾花数据集
Y=Y1  #若X=X2,Y=Y2表示采用酒类数据集
m,d=X.shape      # m为样本数，d为特征数
m,l=Y.shape      # l为输出向量维数
q=8              # 隐层神经元数目

para0=initialpara(d,q,l)

#%%============================================
#   考察不同固定学习率对标准BP算法收敛情况的影响
#==============================================

plt.figure()
plt.xlabel('迭代次数')
plt.ylabel('累积均方误差')
plt.title('鸢尾花数据集-标准BP(隐层数q=8)-固定学习率')
ite=500          # 迭代次数
for alpha in [0.1,1,3,5]:
    para,erro=BP(X,Y,q,para0,num=1,alpha=alpha,iteration=ite)
    plt.plot(np.arange(len(erro))+1,erro,label='α=%.2f'%alpha,linewidth=0.6)
plt.legend()
plt.show()



#%%======================
#   考察BP_Linear算法
#========================
#   BP_Linear算法超参数有三个：初始学习率，终了学习率，tmax

plt.figure()

ite=500

a1=[0.1,2]
for a in a1:
    para,erro=BP(X,Y,q,para0,num=1,alpha=a,iteration=ite)
    plt.plot(np.arange(len(erro))+1,erro,label='标准BP(学习率%.1f)'%a,linewidth=0.6)

tmax=250
a1=[2]
a2=[0.1]
for a11 in a1:
    for a22 in a2:
        para,erro=BP_Linear(X,Y,q,para0,num=1,alpha1=a11,alpha2=a22,tmax=tmax,iteration=ite)
        plt.plot(np.arange(len(erro))+1,erro,
                 label='BP_Linear(学习率: %.2f→%.2f,tmax=%d)'%(a11,a22,tmax),linewidth=1)

plt.xlabel('迭代次数')
plt.ylabel('累积均方误差')
plt.title('鸢尾花数据集-隐层数q=8-动态调整学习率')
plt.legend()
plt.show()


#【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】
#%%=================================================
#       在酒类数据集上进行计算
#                数据集设置以及网络参数设置
#===================================================
X=X2  #若X=X1,Y=Y1表示采用鸢尾花数据集
X=(X-np.mean(X,axis=0))/np.std(X,axis=0)  # z-score归一化
Y=Y2  #若X=X2,Y=Y2表示采用酒类数据集
m,d=X.shape      # m为样本数，d为特征数
m,l=Y.shape      # l为输出向量维数
q=20              # 隐层神经元数目

para0=initialpara(d,q,l)

#%%============================================
#   考察不同固定学习率对标准BP算法收敛情况的影响
#==============================================
#   BP_Linear算法超参数有三个：初始学习率，终了学习率，tmax

plt.figure()
plt.xlabel('迭代次数')
plt.ylabel('累积均方误差')
plt.title('酒类数据集-标准BP(隐层数q=20)-固定学习率')
ite=500          # 迭代次数
for alpha in [0.1,0.5,3,10]:
    para,erro=BP(X,Y,q,para0,num=1,alpha=alpha,iteration=ite)
    plt.plot(np.arange(len(erro))+1,erro,label='α=%.2f'%alpha,linewidth=0.6)
plt.legend()
plt.show()



#%%======================
#   考察BP_Linear算法
#========================
#   BP_Linear算法超参数有三个：隐藏层学习率、输出层学习率,

plt.figure()

ite=500

a1=[0.5,10]
for a in a1:
    para,erro=BP(X,Y,q,para0,num=1,alpha=a,iteration=ite)
    plt.plot(np.arange(len(erro))+1,erro,label='标准BP(学习率%.1f)'%a,linewidth=0.6)

tmax=300
a1=[10]
a2=[0.1]
for a11 in a1:
    for a22 in a2:
        para,erro=BP_Linear(X,Y,q,para0,num=1,alpha1=a11,alpha2=a22,tmax=tmax,iteration=ite)
        plt.plot(np.arange(len(erro))+1,erro,
                 label='BP_Linear(学习率: %.2f→%.2f,tmax=%d)'%(a11,a22,tmax),linewidth=1)

plt.xlabel('迭代次数')
plt.ylabel('累积均方误差')
plt.title('酒类数据集-隐层数q=20-动态调整学习率')
plt.legend()
plt.show()
